using MediatR;
using Microsoft.Extensions.Logging;
using RBAC.Domain.Dto.Output;
using RBAC.Domain.ProcessManagement;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Read.Api.Application.Command.ProcessManagements;
using System.Linq;
using System.Collections.Generic;

namespace RBAC.Read.Api.Application.Handler.ProcessManagements
{
    /// <summary>
    /// 工艺流程 列表分页 处理器
    /// </summary>
    public class GetProcessFlowsPageHandler : IRequestHandler<GetProcessFlowsPageCommand, APIPaging<ProcessFlowListDto>>
    {
        private readonly IBaseRepository<ProcessFlow> _repo;
        private readonly ILogger<GetProcessFlowsPageHandler> _logger;

        public GetProcessFlowsPageHandler(IBaseRepository<ProcessFlow> repo, ILogger<GetProcessFlowsPageHandler> logger)
        {
            _repo = repo;
            _logger = logger;
        }

        public Task<APIPaging<ProcessFlowListDto>> Handle(GetProcessFlowsPageCommand request, CancellationToken cancellationToken)
        {
            var result = new APIPaging<ProcessFlowListDto>();
            try
            {
                var (where, param) = BuildWhere(request);

                // 统计总数
                var countSql = $@"SELECT COUNT(1)
                                   FROM ProcessFlow pf
                                   LEFT JOIN Department dm ON pf.DepartmentId = dm.Id AND dm.IsDeleted = 0
                                   LEFT JOIN `User` u ON pf.OwnerUserId = u.Id AND u.IsDeleted = 0
                                   {(string.IsNullOrWhiteSpace(where) ? "" : "WHERE " + where)}";
                var total = _repo.QueryFirstOrDefault<int>(countSql, param);

                // 数据查询
                var dataSql = $@"SELECT
                                    pf.Id,
                                    pf.FlowCode,
                                    pf.SystemCode,
                                    pf.FlowName,
                                    pf.ProcessCount,
                                    pf.OwnerUserId,
                                    COALESCE(u.UserName, pf.OwnerUserName) AS OwnerUserName,
                                    pf.DepartmentId,
                                    COALESCE(dm.DepartmentName, pf.DepartmentName) AS DepartmentName,
                                    pf.Status,
                                    pf.Remark,
                                    pf.CreateTime,
                                    pf.CreateUser
                                  FROM ProcessFlow pf
                                  LEFT JOIN Department dm ON pf.DepartmentId = dm.Id AND dm.IsDeleted = 0
                                  LEFT JOIN `User` u ON pf.OwnerUserId = u.Id AND u.IsDeleted = 0
                                  {(string.IsNullOrWhiteSpace(where) ? "" : "WHERE " + where)}
                                  ORDER BY {request.OrderBy}
                                  LIMIT @Offset, @PageSize";

                param["Offset"] = (request.PageIndex - 1) * request.PageSize;
                param["PageSize"] = request.PageSize;

                var rows = _repo.Query<ProcessFlowListDto>(dataSql, param) ?? new List<ProcessFlowListDto>();

                // 为当前页流程批量查询明细与附件并回填
                if (rows.Count > 0)
                {
                    var ids = rows.Select(r => r.Id).ToList();

                    // 明细
                    var detailSql = @"SELECT Id, FlowId, Sort, ProcessId, ProcessCode, ProcessName, OwnerUserId, OwnerUserName, DepartmentId, DepartmentName, Remark
                                       FROM ProcessFlowDetail
                                       WHERE IsDeleted = 0 AND FlowId IN @Ids
                                       ORDER BY FlowId, Sort";
                    var details = _repo.Query<ProcessFlowDetailDto>(detailSql, new { Ids = ids }) ?? new List<ProcessFlowDetailDto>();
                    var detailLookup = details.GroupBy(d => d.FlowId).ToDictionary(g => g.Key, g => g.ToList());

                    // 附件
                    var attSql = @"SELECT FlowId, FileName, FileUrl, FileSize, ContentType, Status, Remark
                                   FROM ProcessFlowAttachment
                                   WHERE IsDeleted = 0 AND FlowId IN @Ids";
                    var atts = _repo.Query<ProcessFlowAttachmentDto>(attSql, new { Ids = ids }) ?? new List<ProcessFlowAttachmentDto>();
                    var attLookup = atts.GroupBy(a => a.FlowId).ToDictionary(g => g.Key, g => g.ToList());

                    foreach (var r in rows)
                    {
                        if (detailLookup.TryGetValue(r.Id, out var dlist))
                            r.Details = dlist;
                        else
                            r.Details = new List<ProcessFlowDetailDto>();

                        if (attLookup.TryGetValue(r.Id, out var alist))
                            r.Attachments = alist;
                        else
                            r.Attachments = new List<ProcessFlowAttachmentDto>();
                    }
                }

                result.Code = APIEnums.Success;
                result.PageDatas = rows;
                result.TotalCount = total;
                result.Msg = "获取工艺流程列表成功";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取工艺流程列表失败: {Message}", ex.Message);
                result.Code = APIEnums.Error;
                result.Msg = "获取工艺流程列表失败";
                result.PageDatas = new List<ProcessFlowListDto>();
                result.TotalCount = 0;
            }

            return Task.FromResult(result);
        }

        private (string where, Dictionary<string, object> param) BuildWhere(GetProcessFlowsPageCommand req)
        {
            var conds = new List<string> { "pf.IsDeleted = 0" };
            var p = new Dictionary<string, object>();

            if (!string.IsNullOrWhiteSpace(req.Keyword))
            {
                conds.Add("(pf.FlowCode LIKE @kw OR pf.FlowName LIKE @kw)");
                p["kw"] = $"%{req.Keyword}%";
            }
            if (req.DepartmentId.HasValue)
            {
                conds.Add("pf.DepartmentId = @DepartmentId");
                p["DepartmentId"] = req.DepartmentId.Value;
            }
            if (req.Status.HasValue)
            {
                conds.Add("pf.Status = @Status");
                p["Status"] = req.Status.Value;
            }

            var where = string.Join(" AND ", conds);
            return (where, p);
        }
    }
}
